import jsbeautify from 'js-beautify';

/**
 * 格式化 Api Key值
 *
 * @param { String } path 全部路径
 * @param { String } key 文件名
 * @param { String } type 请求类型
 * @param { Array } IgnorePathArray 额外过滤数组
 * @param { Object } pathMapping 检查是否有重名Key值的Mapping
 * @return { String } Key值
 */
export const FormatPathName = (path, key, type, IgnorePathArray, pathMapping) => {
    if (path.indexOf('/' + key) != -1) {
        path = path.replace('/' + key, '');
    };
    for (let i = 0; i < IgnorePathArray.length; i++) {
        const element = IgnorePathArray[i];
        if (path.indexOf('/' + element) != -1) {
            path = path.replace('/' + element, '');
        };
    };
    if (path.indexOf('/') == 0) {
        path = path.replace('/', '');
    };
    path = path && path.replace(/\//g, '_');
    path = path || 'root';
    if (!pathMapping[path]) {
        pathMapping[path] = true
    } else {
        path = path + '_' + type;
    };
    return path;
}

/**
 * 格式化参数类型 （TS 版）
 *
 * @param { Object } Config Swagger Api parameters 字段
 * @param { String } type 类型 （header 、query）
 * @return { String } 参数返回值
 */
export const FormatParmas = (Config, type, FileName) => {
    var Src = [];
    for (let i = 0; i < Config.length; i++) {
        const element = Config[i];
        if (element.in == type) {
            var Type = 'any';
            if (element.schema && ['number', 'string', 'integer', 'boolean'].includes(element.schema.type)) {
                if (element.schema.type == 'integer') {
                    Type = 'number'
                };
            } else if (element.schema) {
                Type = `${FileName}.${FormatConfigType(element.schema || {})}`;
            };
            Src.push(`        /** ${element.description || ''} */\n        ${element.name}: ${Type}`);
        }
    };
    if (Src.length) {
        return '{\n' + Src.join(',\n') + '\n    }';
    } else {
        return false;
    };
}

/**
 * 格式化参数类型 （注释 版）
 *
 * @param { Object } Config Swagger Api parameters 字段
 * @param { String } type 类型 （header 、query）
 * @return { String } 参数返回值
 */
export const FormatExampleParmas = (Config, type, FileName) => {
    var Src = '{\n';
    for (let i = 0; i < Config.length; i++) {
        const element = Config[i];
        if (element.in == type) {
            var Type = 'any';
            if (element.schema && ['number', 'string', 'integer', 'boolean'].includes(element.schema.type)) {
                if (element.schema.type == 'integer') {
                    Type = 'number'
                };
            } else if (element.schema) {
                Type = `${FileName}.${FormatConfigType(element.schema || {})}`;
            };
            Src += `    ${element.name}: ${Type}, ${element.description ? ' // ' + element.description : ''}\n`;
        }
    };
    return Src + '}'
}

/**
 * 格式化 Body 类型
 *
 * @param { Object } Config Swagger application/json 参数格式化类型
 * @param { String } FileName 文件名
 * @return { String } Body 类型
 */
export const FormatBody = (Config, FileName) => {
    return `${FileName}.${FormatConfigType(Config.schema)}`;
}

/**
 * 格式化 Response 类型
 *
 * @param { Object } Config Swagger application/json 参数格式化类型
 * @param { String } FileName 文件名
 * @return { String } Body 类型
 */
export const FormatResponse = (Config, FileName) => {
    var type = FormatConfigType(Config.schema);
    if (['number', 'string', 'integer', 'boolean', 'any'].includes(type)) {
        return Config.schema.type;
    } else {
        return `${FileName}.${type}`;
    }
}

/**
 * 删除关键字中 [,,] 的多维表达式类型
 *
 * @param { String } key 文件名
 * @return { String } 格式化后的文件名
 */
export const FormatKey = (key) => {
    return key.replace(/\[.*\]/, () => {
        return '_'
    })
}

/**
 * 格式化数组类型
 *
 * @param { Object } Config Swagger 参数类型（数组）
 * @return { String } 字符串
 */
export const FormatArrayType = (Config) => {
    return FormatConfigType(Config.items) + '[]';
}

/**
 * 格式化对象中的单个参数类型
 *
 * @param { Object } Config Swagger 参数类型
 * @return { String } 字符串
 */
export const FormatConfigType = (Config) => {
    var Str = '';
    if (Config && Config.type == 'array') {
        Str += FormatArrayType(Config);
    } else if (Config.$ref) {
        var _key = Config.$ref.replace('#/components/schemas/', '');
        Str += FormatKey(_key);
    } else if (Config.enum) {
        Str += Config.enum.join(' | ');
    } else if (['number', 'string', 'integer', 'boolean'].includes(Config.type)) {
        var Type = Config.type
        if (Config.type == 'integer') {
            Type = 'number'
        };
        Str += Type;
    } else {
        Str += 'any';
    };
    return Str;
}

/**
 * 格式化 TS Interface 参数类型 
 *
 * @param { Object } Config Swagger 参数类型
 * @param { String } key 关键字
 * @return { String } 字符串
 */

export const FormatInterface = (Config, key) => {
    var Str = '';
    if (Config.type == 'object') {
        var Index = 0;
        Str += `    /**
     * ${Config.description || ''}
     * @interface ${FormatKey(key)}
     */
    interface ${FormatKey(key)} {\n`
        for (const key in Config.properties) {
            Index++
            const element = Config.properties[key];
            var description = element.description ? element.description.replace(/\r\n/g, ' ') : '';
            Str += `        /** ${description} */\n`;
            Str += `        ${key}${element.nullable ? '?' : ''}: ${FormatConfigType(element)},\n`
        }
        if (Index == 0) {
            Str += `        [x: string]: any,\n`;
        }
        Str += `    }\n\n\n`;
    };
    if (Config.enum && Config.type != 'object') {
        Str += `    /**
     * ${Config.description || ''}
     */
    type ${key} = ${Config.enum.join(' | ')};\n\n\n`
    };
    return Str;
}

/**
 * 美化 JSON 字符串
 *
 * @param { String } source JSON 字符串
 * @return { String } 
 */
export const Beautify = source => {
    var opts = {};
    opts.indent_char = ' ';
    opts.preserve_newlines = "-1";
    return jsbeautify.js(source, opts);
}

/**
 * 给 Swagger 独享 添加注释
 *
 * @param { Object } item 对象类型
 * @param { String } key 关键字
 * @return { String } 
 */
export const RenderAnnotation = (item, key) => {
    var description = item.description ? item.description.replace(/\r\n/g, '') : ' ';
    return ` // ${description} ${key || ''} (${item.format || item.type || ''}) ${!item.nullable ? '必填' : ''}${item.enum ? ' 备选值 ：' + JSON.stringify(item.enum) : ''}`;
}

/**
 * 格式化 JSON 数组类型
 *
 * @param { Object } Config Swagger 参数 对象
 * @param { Object } Schema Swagger 对象参数
 * @param { Array } parentKeys 父级Key值列表 （中断递归判断条件）
 * @param { String } FileName 命名空间
 * @return { String } 
 */
export const FormatArrayJson = (Config, Schema, parentKeys, FileName) => {
    var Str = '';
    if (Config.items && Config.items.$ref) {
        Str += `[ ${RenderAnnotation(Config.items, 'array')}\n${FormatJson(Config.items, Schema, FileName, parentKeys)}\n],`
    } else {
        Str += `[] ${!parentKeys.length ? ',' : ''} ${RenderAnnotation(Config.items, 'array')}`;
    }
    return Str
}

/**
 * 格式化 JSON 对象
 *
 * @param { Object } Config Swagger 参数 对象
 * @param { Object } Schema Swagger 对象参数
 * @param { String } key 类型关键字
 * @param { Array } parentKeys 父级Key值列表 （中断递归判断条件）
 * @param { String } FileName 命名空间
 * @return { String } 
 */
export const FormatObjectJson = (Config, Schema, key, parentKeys, FileName) => {
    var Str = `{ ${RenderAnnotation(Config, FileName + '.' + key)}\n`;
    for (const key in Config.properties) {
        const element = Config.properties[key];
        Str += `${key}: ${FormatJson(element, Schema, FileName, parentKeys)}\n`;
    };
    return Str += '}'
}

/**
 * 给 JS 模式参数添加 默认值
 *
 * @param { Object } Config Swagger 选项
 * @param { Array } parentKeys 父级Key值列表
 * @return { String }  格式化后的字符串
 */
export const FormatItem = (Config, parentKeys) => {
    var value = null;
    switch (Config.type) {
        case 'string':
            value = '""';
            break;
        case 'number':
            value = '0';
            break;
        case 'integer':
            value = '0';
            break;
        case 'boolean':
            value = 'true';
            break;
        default:
            value = '""';
            break;
    }
    return `${value} ${!parentKeys.length ? ',' : ''} ${RenderAnnotation(Config)}`;
}

/**
 * 格式化 JSON 对象类型
 *
 * @param { Object } Config Swagger 选项
 * @param { Object } Schema Swagger 对象参数
 * @param { String } FileName 命名空间
 * @param { Array } [parentKeys=[]] 父级Key值列表
 * @return { String } 
 */
export const FormatJson = (Config, Schema, FileName, parentKeys = []) => {
    var Str = '';
    if (Config.type && Config.type == 'array') {
        Str += FormatArrayJson(Config, Schema, parentKeys, FileName);
    } else if (Config.$ref) {
        var key = FormatKey(Config.$ref.replace('#/components/schemas/', ''));
        if (!parentKeys.includes(key)) {
            var _parentKeys = parentKeys.concat([key]);
            if (Schema[key] && Schema[key].type == 'object') {
                Str += FormatObjectJson(Schema[key], Schema, key, _parentKeys, FileName) + ',';
            } else if (Schema[key]) {
                Str += FormatItem(Config, parentKeys);
            }
        };
    } else {
        Str += FormatItem(Config, parentKeys);
    };
    return Str;
}
